package com.jiufengxinxi.ts.device.equipment;

import com.jiufengxinxi.ts.device.interfaces.ICommDevice;
import com.thingmagic.*;
import gnu.io.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Enumeration;

public class SerialTransportRXTX implements SerialTransport {
	
	private final Logger logger= LoggerFactory.getLogger(ICommDevice.class);
	
	private String serialUri;
	
	private CommPortIdentifier commPort;
	
	private SerialPort serialPort;
	
	private InputStream inputStream;
	
    private OutputStream outputStream;
    
    private int baudrate = 115200;
    
    
    private static SerialTransportRXTX serialTransportRXTX;
    
    public static SerialTransportRXTX getInstence(String serialUri) {
    	serialUri = "COM5";
    	if(serialTransportRXTX==null) {
    		serialTransportRXTX = new SerialTransportRXTX(serialUri);
    	}
    	serialTransportRXTX.setSerialUri(serialUri);
    	return serialTransportRXTX;
    }
	

	public SerialTransportRXTX(String serialUri) {
		super();
		this.serialUri = serialUri;
	}

	@Override
	public void open() throws ReaderException {
		try {
			Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers(); 
			while (portList.hasMoreElements()) {
	    	  		String tport=portList.nextElement().getName();
		        System.out.println("找到串口："+tport);
		        if(tport.equals(serialUri)){
			        	  	try {
							commPort= CommPortIdentifier.getPortIdentifier(serialUri);
						} catch (NoSuchPortException e) {
							e.printStackTrace();
						}
			        	  break;
		          }
		      }
			
			if(commPort==null){
				logger.error("读写器串口不存在");
				throw new ReaderException("读写器串口不存在 "+serialUri);
			}
			serialPort = (SerialPort)commPort.open(serialUri, 300);
			serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
			inputStream = serialPort.getInputStream();
			outputStream = serialPort.getOutputStream();
			System.out.println("open ok ~~!!!!");
		} catch (PortInUseException | IOException | UnsupportedCommOperationException e) {
			e.printStackTrace();
			if(e instanceof PortInUseException) {
				logger.error("读写器串口in used");
			}else {
				shutdown();
			}
			throw new ReaderException(e.getMessage());
		}
	}

	@Override
	public void sendBytes(int length, byte[] message, int offset, int timeoutMs) throws ReaderException {
		// TODO Auto-generated method stub
	       try
	        {
	            if(outputStream == null)
	            {
	               throw new ReaderException("serial Connection lost");
	            }
	            //System.out.println("sendBytes : " + HexUtils.bytesToHexFun1(message));

	            outputStream.write(message, offset, length);
	        }
	        catch(Exception ex)
	        {
	          throw new ReaderCommException(ex.getMessage());
	        }
	}

	@Override
	public byte[] receiveBytes(int length, byte[] messageSpace, int offset, int timeoutMillis) throws ReaderException {
		// TODO Auto-generated method stub
	       try
	        {
	            if(inputStream == null)
	            {
	               throw new IOException("TCP Connection lost");
	            }
	            int responseWaitTime = 0;
	            while (inputStream.available() < length && responseWaitTime <timeoutMillis)
	            {
	                Thread.sleep(10);
	                // Repeat the loop for every 10 milli sec untill we receive required
	                // data
	                responseWaitTime+=10;
	            }
	            if (inputStream.available() <= 0)
	            {
	                throw new IOException("Timeout");
	            }
	            inputStream.read(messageSpace, offset, length);
				//System.out.println("receiveBytes : %x   " + HexUtils.bytesToHexFun1(messageSpace));
	        }
	        catch(Exception ex)
	        {
	          throw new ReaderCommException(ex.getMessage());
	        }
	        return messageSpace;
	}

	public String getSerialUri() {
		return serialUri;
	}


	public void setSerialUri(String serialUri) {
		this.serialUri = serialUri;
	}


	public CommPortIdentifier getCommPort() {
		return commPort;
	}


	public void setCommPort(CommPortIdentifier commPort) {
		this.commPort = commPort;
	}


	public SerialPort getSerialPort() {
		return serialPort;
	}


	public void setSerialPort(SerialPort serialPort) {
		this.serialPort = serialPort;
	}


	public InputStream getInputStream() {
		return inputStream;
	}


	public void setInputStream(InputStream inputStream) {
		this.inputStream = inputStream;
	}


	public OutputStream getOutputStream() {
		return outputStream;
	}


	public void setOutputStream(OutputStream outputStream) {
		this.outputStream = outputStream;
	}


	public int getBaudrate() {
		return baudrate;
	}


	public void setBaudrate(int baudrate) {
		this.baudrate = baudrate;
	}


	public Logger getLogger() {
		return logger;
	}


	@Override
	public int getBaudRate() throws ReaderException {
		return baudrate;
	}

	@Override
	public void setBaudRate(int rate) throws ReaderException {
		if(serialPort!=null) {
			//try {
				System.out.println("rate  "+rate);
				baudrate = rate;
				//serialPort.setBaudBase(rate);
//			} catch (UnsupportedCommOperationException | IOException e) {
//				e.printStackTrace();
//				//throw new ReaderException(e.getMessage());
//			}
		}
	}

	@Override
	public void flush() throws ReaderException {
//		try {
//			outputStream.flush();
//		} catch (IOException e) {
//			throw new ReaderException(e.getMessage());
//		}
	}

	@Override
	public void shutdown() throws ReaderException {
    	System.out.println("+++++++++++++++++++++++++++++++++++shut down++++++++++++++++++++++++++++++++++++++++++");
		if(inputStream!=null) {
			try {
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		if(outputStream!=null) {
			try {
				outputStream.flush();
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if(serialPort!=null) {
			serialPort.close();
		}
	}
	
	
	
	static public class Factory implements ReaderFactory
	  { 

	      public SerialReader createReader(String uriString) throws ReaderException
	      {
	          String readerUri = null;
	          try 
	          {
	              URI uri = new URI(uriString);
	              readerUri = uri.getPath();
	          } 
	          catch (Exception ex) 
	          {
	              
	          }
	          return new SerialReader(readerUri, SerialTransportRXTX.getInstence(readerUri));
	      }
	    }

}
